﻿using System.Collections.Generic;
using System.Linq;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleSkill;

namespace Runtime.Models {

    public partial interface IDFR_BattleCellModelTD {

        IDFR_BattleBuffProviderSetter AsBuffProviderSetter();
    }

    public partial interface IDFR_BattleCellModelTDSetter {

        /// <summary>
        /// 目标进入
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        void Enter(DFR_BattleEntityInstanceID targetEntityInstanceID);

        /// <summary>
        /// 目标离开
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        void Exit(DFR_BattleEntityInstanceID targetEntityInstanceID);
    }

    public abstract partial class DFR_BattleCellModelTD : IDFR_BattleBuffProvider, IDFR_BattleBuffProviderSetter, IDFR_BattleCellModelTDSetter {

        public IDFR_BattleBuffProviderSetter AsBuffProviderSetter() => this;

        IDFR_BattleBuffProviderSetter IDFR_BattleBuffProvider.AsSetter() => this;

        bool IDFR_BattleBuffProvider.IsEnablePersistence => false;

        [Autowired]
        private readonly IDFR_BattleBuffProviderSetter m_BuffProvider;

        private Dictionary<IDFR_BattleBuffProvider, DFR_BattleEntityHandle> m_IncludeBuffProviderDictionary = new();

        public IDFR_ReadOnlyBattleData HPBase => m_BuffProvider.HPBase;

        public IDFR_ReadOnlyBattleData HPFactor => m_BuffProvider.HPFactor;

        public IDFR_ReadOnlyBattleData HPAdditional => m_BuffProvider.HPAdditional;

        public IDFR_ReadOnlyBattleData HPMaxBase => m_BuffProvider.HPMaxBase;

        public IDFR_ReadOnlyBattleData HPMaxFactor => m_BuffProvider.HPMaxFactor;

        public IDFR_ReadOnlyBattleData HPMaxAdditional => m_BuffProvider.HPMaxAdditional;

        public IDFR_ReadOnlyBattleData DamageHPMaxBase => m_BuffProvider.DamageHPMaxBase;

        public IDFR_ReadOnlyBattleData DamageHPMaxFactor => m_BuffProvider.DamageHPMaxFactor;

        public IDFR_ReadOnlyBattleData DamageHPMaxAdditional => m_BuffProvider.DamageHPMaxAdditional;

        public IDFR_ReadOnlyBattleData DamageHPBase => m_BuffProvider.DamageHPBase;

        public IDFR_ReadOnlyBattleData DamageHPFactor => m_BuffProvider.DamageHPFactor;

        public IDFR_ReadOnlyBattleData DamageHPAdditional => m_BuffProvider.DamageHPAdditional;

        public IDFR_ReadOnlyBattleData DamageBase => m_BuffProvider.DamageBase;

        public IDFR_ReadOnlyBattleData DamageFactor => m_BuffProvider.DamageFactor;

        public IDFR_ReadOnlyBattleData DamageAdditional => m_BuffProvider.DamageAdditional;

        public IDFR_ReadOnlyBattleData AttackBase => m_BuffProvider.AttackBase;

        public IDFR_ReadOnlyBattleData AttackFactor => m_BuffProvider.AttackFactor;

        public IDFR_ReadOnlyBattleData AttackAdditional => m_BuffProvider.AttackAdditional;

        public IDFR_ReadOnlyBattleData AttackBossAdditionalBase => m_BuffProvider.AttackBossAdditionalBase;

        public IDFR_ReadOnlyBattleData AttackBossAdditionalFactor => m_BuffProvider.AttackBossAdditionalFactor;

        public IDFR_ReadOnlyBattleData AttackBossAdditionalAdditional => m_BuffProvider.AttackBossAdditionalAdditional;

        public IDFR_ReadOnlyBattleData AttackSpeedBase => m_BuffProvider.AttackSpeedBase;

        public IDFR_ReadOnlyBattleData AttackSpeedFactor => m_BuffProvider.AttackSpeedFactor;

        public IDFR_ReadOnlyBattleData AttackSpeedAdditional => m_BuffProvider.AttackSpeedAdditional;

        public IDFR_ReadOnlyBattleData CriticalBase => m_BuffProvider.CriticalBase;

        public IDFR_ReadOnlyBattleData CriticalFactor => m_BuffProvider.CriticalFactor;

        public IDFR_ReadOnlyBattleData CriticalAdditional => m_BuffProvider.CriticalAdditional;

        public IDFR_ReadOnlyBattleData CriticalPowerBase => m_BuffProvider.CriticalPowerBase;

        public IDFR_ReadOnlyBattleData CriticalPowerFactor => m_BuffProvider.CriticalPowerFactor;

        public IDFR_ReadOnlyBattleData CriticalPowerAdditional => m_BuffProvider.CriticalPowerAdditional;

        public IDFR_ReadOnlyBattleData SpottingRangeBase => m_BuffProvider.SpottingRangeBase;

        public IDFR_ReadOnlyBattleData SpottingRangeFactor => m_BuffProvider.SpottingRangeFactor;

        public IDFR_ReadOnlyBattleData SpottingRangeAdditional => m_BuffProvider.SpottingRangeAdditional;

        public IDFR_ReadOnlyBattleData MoveSpeedBase => m_BuffProvider.MoveSpeedBase;

        public IDFR_ReadOnlyBattleData MoveSpeedFactor => m_BuffProvider.MoveSpeedFactor;

        public IDFR_ReadOnlyBattleData MoveSpeedAdditional => m_BuffProvider.MoveSpeedAdditional;

        public IDFR_ReadOnlyBattleData DefenseBase => m_BuffProvider.DefenseBase;

        public IDFR_ReadOnlyBattleData DefenseFactor => m_BuffProvider.DefenseFactor;

        public IDFR_ReadOnlyBattleData DefenseAdditional => m_BuffProvider.DefenseAdditional;

        public IDFR_ReadOnlyBattleData DodgeBase => m_BuffProvider.DodgeBase;

        public IDFR_ReadOnlyBattleData DodgeFactor => m_BuffProvider.DodgeFactor;

        public IDFR_ReadOnlyBattleData DodgeAdditional => m_BuffProvider.DodgeAdditional;

        public IDFR_ReadOnlyBattleData InfluenceAmountAdditional => m_BuffProvider.InfluenceAmountAdditional;

        DFR_BattleEntityInstanceID IDFR_BattleBuffProvider.OwnerEntityInstanceID => OwnerPlayerInstanceID;

        DFR_BattleEntityInstanceID IDFR_BattleBuffProvider.SourceEntityInstanceID => DFR_BattleEntityInstanceID.Empty;

        private partial bool InitializeBuffProvider() {
            (m_BuffProvider as IDFR_BattleBuffProviderInternal).Initialize(EntityInstanceID, true, OwnerPlayerInstanceID, DFR_BattleEntityInstanceID.Empty);
            return true;
        }


        private partial void DisposeBuffProvider() {
            foreach (var kv in m_IncludeBuffProviderDictionary) {
                kv.Key.Dispose();
            }
            m_IncludeBuffProviderDictionary = null;
        }

        public void AttachBuff(IDFR_BattleBuffProvider source) {
            m_BuffProvider.AttachBuff(source);
            m_IncludeBuffProviderDictionary[source] = DFR_BattleEntityHandle.Empty;
            AcitveBuff(source);
        }

        public void DetachBuff(IDFR_BattleBuffProvider source) {
            m_BuffProvider.DetachBuff(source);
            InactiveBuff(source);
            m_IncludeBuffProviderDictionary.Remove(source);
        }

        private void AcitveBuff(IDFR_BattleBuffProvider buffProvider) {
            if ((!m_IncludeBuffProviderDictionary.TryGetValue(buffProvider, out var entityHandle) || entityHandle == DFR_BattleEntityHandle.Empty)
                && CanActiveBuff(OwnerPlayerID, buffProvider) && buffProvider is IDFR_BattleEffectHolder effectHolder && effectHolder.HasModelAsset) {

                entityHandle = BattleServiceBase.Instance.AttachHolder(effectHolder, Axis);
                if (entityHandle == DFR_BattleEntityHandle.Empty) {
                    UnityEngine.Debug.LogWarning($"在 {nameof(AcitveBuff)} 中 {nameof(BattleServiceBase.Instance.AttachHolder)} 时，返回的 {nameof(DFR_BattleEntityHandle)} 为 {nameof(DFR_BattleEntityHandle.Empty)}");
                } else {
                    m_IncludeBuffProviderDictionary[buffProvider] = entityHandle;
                }
            }
        }

        private void InactiveBuff(IDFR_BattleBuffProvider buffProvider) {
            if (m_IncludeBuffProviderDictionary.TryGetValue(buffProvider, out var entityHandle) && entityHandle != DFR_BattleEntityHandle.Empty
                && buffProvider is IDFR_BattleEffectHolder) {

                m_IncludeBuffProviderDictionary[buffProvider] = DFR_BattleEntityHandle.Empty;
                BattleServiceBase.Instance.DetachHolder(entityHandle);
            }
        }

        protected partial void AttachBuff() {
            if (DFR_BattleTD.DataCenter.Models.AttackSourceDictionary.TryGetValue(ContentEntityInstanceID.Value, out var model)) {
                var attackSourceModel = model.AsSetter();
                attackSourceModel.Attack.Base.Add(m_BuffProvider.AttackBase);
                attackSourceModel.Attack.Factor.Add(m_BuffProvider.AttackFactor);
                attackSourceModel.Attack.Additional.Add(m_BuffProvider.AttackAdditional);
                attackSourceModel.AttackBossAdditional.Base.Add(m_BuffProvider.AttackBossAdditionalBase);
                attackSourceModel.AttackBossAdditional.Factor.Add(m_BuffProvider.AttackBossAdditionalFactor);
                attackSourceModel.AttackBossAdditional.Additional.Add(m_BuffProvider.AttackBossAdditionalAdditional);
                attackSourceModel.AttackSpeed.Base.Add(m_BuffProvider.AttackSpeedBase);
                attackSourceModel.AttackSpeed.Factor.Add(m_BuffProvider.AttackSpeedFactor);
                attackSourceModel.AttackSpeed.Additional.Add(m_BuffProvider.AttackSpeedAdditional);
                attackSourceModel.Critical.Base.Add(m_BuffProvider.CriticalBase);
                attackSourceModel.Critical.Factor.Add(m_BuffProvider.CriticalFactor);
                attackSourceModel.Critical.Additional.Add(m_BuffProvider.CriticalAdditional);
                attackSourceModel.CriticalPower.Base.Add(m_BuffProvider.CriticalPowerBase);
                attackSourceModel.CriticalPower.Factor.Add(m_BuffProvider.CriticalPowerFactor);
                attackSourceModel.CriticalPower.Additional.Add(m_BuffProvider.CriticalPowerAdditional);
                attackSourceModel.SpottingRange.Base.Add(m_BuffProvider.SpottingRangeBase);
                attackSourceModel.SpottingRange.Factor.Add(m_BuffProvider.SpottingRangeFactor);
                attackSourceModel.SpottingRange.Additional.Add(m_BuffProvider.SpottingRangeAdditional);
                var keys = m_IncludeBuffProviderDictionary.Keys.ToArray();
                foreach (var includeBuffProvider in keys) {
                    AcitveBuff(includeBuffProvider);
                }
            }
        }

        protected partial void DetachBuff() {
            if (DFR_BattleTD.DataCenter.Models.AttackSourceDictionary.TryGetValue(ContentEntityInstanceID.Value, out var model)) {
                var attackSourceModel = model.AsSetter();
                attackSourceModel.Attack.Base.Remove(m_BuffProvider.AttackBase);
                attackSourceModel.Attack.Factor.Remove(m_BuffProvider.AttackFactor);
                attackSourceModel.Attack.Additional.Remove(m_BuffProvider.AttackAdditional);
                attackSourceModel.AttackBossAdditional.Base.Remove(m_BuffProvider.AttackBossAdditionalBase);
                attackSourceModel.AttackBossAdditional.Factor.Remove(m_BuffProvider.AttackBossAdditionalFactor);
                attackSourceModel.AttackBossAdditional.Additional.Remove(m_BuffProvider.AttackBossAdditionalAdditional);
                attackSourceModel.AttackSpeed.Base.Remove(m_BuffProvider.AttackSpeedBase);
                attackSourceModel.AttackSpeed.Factor.Remove(m_BuffProvider.AttackSpeedFactor);
                attackSourceModel.AttackSpeed.Additional.Remove(m_BuffProvider.AttackSpeedAdditional);
                attackSourceModel.Critical.Base.Remove(m_BuffProvider.CriticalBase);
                attackSourceModel.Critical.Factor.Remove(m_BuffProvider.CriticalFactor);
                attackSourceModel.Critical.Additional.Remove(m_BuffProvider.CriticalAdditional);
                attackSourceModel.CriticalPower.Base.Remove(m_BuffProvider.CriticalPowerBase);
                attackSourceModel.CriticalPower.Factor.Remove(m_BuffProvider.CriticalPowerFactor);
                attackSourceModel.CriticalPower.Additional.Remove(m_BuffProvider.CriticalPowerAdditional);
                attackSourceModel.SpottingRange.Base.Remove(m_BuffProvider.SpottingRangeBase);
                attackSourceModel.SpottingRange.Factor.Remove(m_BuffProvider.SpottingRangeFactor);
                attackSourceModel.SpottingRange.Additional.Remove(m_BuffProvider.SpottingRangeAdditional);
                var keys = m_IncludeBuffProviderDictionary.Keys.ToArray();
                foreach (var includeBuffProvider in keys) {
                    InactiveBuff(includeBuffProvider);
                }
            }
        }

        void IDFR_BattleCellModelTDSetter.Enter(DFR_BattleEntityInstanceID targetEntityInstanceID) {
            BattleSkillServiceTD.Instance.AddBuff(targetEntityInstanceID, m_BuffProvider);
        }

        void IDFR_BattleCellModelTDSetter.Exit(DFR_BattleEntityInstanceID targetEntityInstanceID) {
            BattleSkillServiceTD.Instance.RemoveBuff(targetEntityInstanceID, m_BuffProvider);
        }
    }
}